/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#ifndef MC_BUILTINS_DICT_VIEWS_H
#define MC_BUILTINS_DICT_VIEWS_H

#include <algorithm>
#include <iterator>
#include <mc/dict.h>
#include <mc/variant.h>
#include <tuple>
#include <type_traits>
#include <vector>

namespace mcpy {

// ============================================================================
// dict_keys_view
// ============================================================================

namespace detail {
/**
 * @brief 字典键视图对象
 *
 * 通过模板参数 Holder 控制存储方式：
 * - 引用类型 → 零拷贝
 * - 值类型 → 拥有数据
 *
 * @tparam K 键类型
 * @tparam Holder 存储类型（const mc::dict& 或 mc::dict）
 */
template <typename K, typename Holder>
class dict_keys_view_impl {
public:
    using value_type = K;

    explicit dict_keys_view_impl(Holder dict) : m_holder(std::forward<Holder>(dict)) {
    }

    // 前向迭代器
    class iterator {
    private:
        mc::dict::const_iterator m_it;

    public:
        using value_type        = K;
        using difference_type   = std::ptrdiff_t;
        using pointer           = const K*;
        using reference         = K;
        using iterator_category = std::forward_iterator_tag;

        iterator() = default;

        explicit iterator(mc::dict::const_iterator it) : m_it(it) {
        }

        K operator*() const {
            if constexpr (std::is_same_v<K, mc::variant>) {
                return m_it->key;
            } else {
                return m_it->key.template as<K>();
            }
        }

        iterator& operator++() {
            ++m_it;
            return *this;
        }

        iterator operator++(int) {
            iterator tmp = *this;
            ++(*this);
            return tmp;
        }

        bool operator!=(const iterator& other) const {
            return m_it != other.m_it;
        }
        bool operator==(const iterator& other) const {
            return m_it == other.m_it;
        }
    };

    using const_iterator = iterator;

    iterator begin() const {
        return iterator(get_dict().begin());
    }
    iterator end() const {
        return iterator(get_dict().end());
    }

    size_t size() const {
        return get_dict().size();
    }

    bool contains(const K& key) const {
        if constexpr (std::is_same_v<K, mc::variant>) {
            return get_dict().contains(key);
        } else {
            return get_dict().contains(mc::variant(key));
        }
    }

    operator mc::array<K>() const {
        mc::array<K> result;
        result.reserve(get_dict().size());
        for (const auto& key : *this) {
            result.push_back(key);
        }
        return result;
    }

    K operator[](size_t index) const {
        auto it = get_dict().begin();
        std::advance(it, index);
        if constexpr (std::is_same_v<K, mc::variant>) {
            return it->key;
        } else {
            return it->key.template as<K>();
        }
    }

private:
    Holder m_holder;

    const mc::dict& get_dict() const {
        if constexpr (std::is_reference_v<Holder>) {
            return m_holder;
        } else {
            return m_holder;
        }
    }
};

} // namespace detail

// 为了兼容性，提供类型别名
template <typename K = mc::variant>
using dict_keys_view = detail::dict_keys_view_impl<K, const mc::dict&>;

// ============================================================================
// dict_values_view
// ============================================================================

namespace detail {
/**
 * @brief 字典值视图对象
 *
 * @tparam V 值类型
 * @tparam Holder 存储类型（const mc::dict& 或 mc::dict）
 */
template <typename V, typename Holder>
class dict_values_view_impl {
public:
    using value_type = V;

    explicit dict_values_view_impl(Holder dict) : m_holder(std::forward<Holder>(dict)) {
    }

    class iterator {
    private:
        mc::dict::const_iterator m_it;

    public:
        using value_type        = V;
        using difference_type   = std::ptrdiff_t;
        using pointer           = const V*;
        using reference         = V;
        using iterator_category = std::forward_iterator_tag;

        iterator() = default;

        explicit iterator(mc::dict::const_iterator it) : m_it(it) {
        }

        V operator*() const {
            if constexpr (std::is_same_v<V, mc::variant>) {
                return m_it->value;
            } else {
                return m_it->value.template as<V>();
            }
        }

        iterator& operator++() {
            ++m_it;
            return *this;
        }

        iterator operator++(int) {
            iterator tmp = *this;
            ++(*this);
            return tmp;
        }

        bool operator!=(const iterator& other) const {
            return m_it != other.m_it;
        }
        bool operator==(const iterator& other) const {
            return m_it == other.m_it;
        }
    };

    using const_iterator = iterator;

    iterator begin() const {
        return iterator(get_dict().begin());
    }
    iterator end() const {
        return iterator(get_dict().end());
    }

    size_t size() const {
        return get_dict().size();
    }

    operator mc::array<V>() const {
        mc::array<V> result;
        result.reserve(get_dict().size());
        for (const auto& value : *this) {
            result.push_back(value);
        }
        return result;
    }

    V operator[](size_t index) const {
        auto it = get_dict().begin();
        std::advance(it, index);
        if constexpr (std::is_same_v<V, mc::variant>) {
            return it->value;
        } else {
            return it->value.template as<V>();
        }
    }

private:
    Holder m_holder;

    const mc::dict& get_dict() const {
        if constexpr (std::is_reference_v<Holder>) {
            return m_holder;
        } else {
            return m_holder;
        }
    }
};

} // namespace detail

// 为了兼容性，提供类型别名
template <typename V = mc::variant>
using dict_values_view = detail::dict_values_view_impl<V, const mc::dict&>;

// ============================================================================
// dict_items_view
// ============================================================================

namespace detail {
/**
 * @brief 字典项视图对象
 *
 * @tparam K 键类型
 * @tparam V 值类型
 * @tparam Holder 存储类型（const mc::dict& 或 mc::dict）
 */
template <typename K, typename V, typename Holder>
class dict_items_view_impl {
public:
    using value_type = std::tuple<K, V>;

    explicit dict_items_view_impl(Holder dict) : m_holder(std::forward<Holder>(dict)) {
    }

    class iterator {
    private:
        mc::dict::const_iterator m_it;

    public:
        using value_type        = std::tuple<K, V>;
        using difference_type   = std::ptrdiff_t;
        using pointer           = const value_type*;
        using reference         = value_type;
        using iterator_category = std::forward_iterator_tag;

        iterator() = default;

        explicit iterator(mc::dict::const_iterator it) : m_it(it) {
        }

        std::tuple<K, V> operator*() const {
            if constexpr (std::is_same_v<K, mc::variant> &&
                          std::is_same_v<V, mc::variant>) {
                return std::make_tuple(m_it->key, m_it->value);
            } else if constexpr (std::is_same_v<K, mc::variant>) {
                return std::make_tuple(m_it->key, m_it->value.template as<V>());
            } else if constexpr (std::is_same_v<V, mc::variant>) {
                return std::make_tuple(m_it->key.template as<K>(), m_it->value);
            } else {
                return std::make_tuple(
                    m_it->key.template as<K>(), m_it->value.template as<V>());
            }
        }

        iterator& operator++() {
            ++m_it;
            return *this;
        }

        iterator operator++(int) {
            iterator tmp = *this;
            ++(*this);
            return tmp;
        }

        bool operator!=(const iterator& other) const {
            return m_it != other.m_it;
        }
        bool operator==(const iterator& other) const {
            return m_it == other.m_it;
        }
    };

    using const_iterator = iterator;

    iterator begin() const {
        return iterator(get_dict().begin());
    }
    iterator end() const {
        return iterator(get_dict().end());
    }

    size_t size() const {
        return get_dict().size();
    }

    operator mc::array<std::tuple<K, V>>() const {
        mc::array<std::tuple<K, V>> result;
        result.reserve(get_dict().size());
        for (const auto& item : *this) {
            result.push_back(item);
        }
        return result;
    }

    std::tuple<K, V> operator[](size_t index) const {
        auto it = get_dict().begin();
        std::advance(it, index);
        return *iterator(it);
    }

private:
    Holder m_holder;

    const mc::dict& get_dict() const {
        if constexpr (std::is_reference_v<Holder>) {
            return m_holder;
        } else {
            return m_holder;
        }
    }
};

} // namespace detail

// 为了兼容性，提供类型别名
template <typename K = mc::variant, typename V = mc::variant>
using dict_items_view = detail::dict_items_view_impl<K, V, const mc::dict&>;

// ============================================================================
// 辅助函数（支持左值/右值重载）
// ============================================================================

/**
 * @brief 获取字典的所有键（左值引用版本 - 零拷贝）
 */
template <typename K = mc::variant>
auto dict_keys(const mc::dict& d) -> detail::dict_keys_view_impl<K, const mc::dict&> {
    return detail::dict_keys_view_impl<K, const mc::dict&>(d);
}

/**
 * @brief 获取字典的所有键（右值拷贝版本 - 拥有数据）
 */
template <typename K = mc::variant>
auto dict_keys(mc::dict&& d) -> detail::dict_keys_view_impl<K, mc::dict> {
    return detail::dict_keys_view_impl<K, mc::dict>(std::move(d));
}

/**
 * @brief 获取字典的所有值（左值引用版本 - 零拷贝）
 */
template <typename V = mc::variant>
auto dict_values(const mc::dict& d) -> detail::dict_values_view_impl<V, const mc::dict&> {
    return detail::dict_values_view_impl<V, const mc::dict&>(d);
}

/**
 * @brief 获取字典的所有值（右值拷贝版本 - 拥有数据）
 */
template <typename V = mc::variant>
auto dict_values(mc::dict&& d) -> detail::dict_values_view_impl<V, mc::dict> {
    return detail::dict_values_view_impl<V, mc::dict>(std::move(d));
}

/**
 * @brief 获取字典的所有项（左值引用版本 - 零拷贝）
 */
template <typename K = mc::variant, typename V = mc::variant>
auto dict_items(const mc::dict& d)
    -> detail::dict_items_view_impl<K, V, const mc::dict&> {
    return detail::dict_items_view_impl<K, V, const mc::dict&>(d);
}

/**
 * @brief 获取字典的所有项（右值拷贝版本 - 拥有数据）
 */
template <typename K = mc::variant, typename V = mc::variant>
auto dict_items(mc::dict&& d) -> detail::dict_items_view_impl<K, V, mc::dict> {
    return detail::dict_items_view_impl<K, V, mc::dict>(std::move(d));
}

} // namespace mcpy

#endif // MC_BUILTINS_DICT_VIEWS_H
